package com.luocc.ccdemo.ui

import android.app.AlertDialog
import android.content.Context
import android.graphics.drawable.Drawable
import android.media.MediaPlayer
import android.net.Uri
import android.os.*
import android.util.Log
import android.view.*
import android.view.animation.Animation
import android.view.animation.AnimationUtils
import android.widget.*
import androidx.core.content.res.ResourcesCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import com.luocc.ccdemo.R
import com.luocc.ccdemo.entity.Video
import com.luocc.ccdemo.utils.DownloadUtil
import com.luocc.ccdemo.vm.VideoViewModel
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.util.*

class VideoPlayingFragment : Fragment() {

    enum class VideoState {
        NONE,
        PAUSE_BY_USER,
        PAUSE_BY_LIFECYCLE,
        PLAYING
    }

    private var mVideo: Video? = null
    private var mTouch: Boolean = false
    private var mSeekBarJob: Job? = null
    private lateinit var mContext: Context
    private var mVideoState = VideoState.NONE
    private lateinit var mRotateAnimation: Animation
    private lateinit var mSurfaceHolder: SurfaceHolder
    private lateinit var mMediaPlayer: MediaPlayer
    private lateinit var mVideoViewModel: VideoViewModel

    private lateinit var mPlay: ImageButton
    private lateinit var mSeekBar: SeekBar
    private lateinit var mProgress: TextView
    private lateinit var mSurfaceView: SurfaceView
    private lateinit var mCollect: ImageButton
    private lateinit var mDownload: ImageButton
    private lateinit var mLoading: ImageView
    private lateinit var mLoadingLayer: ImageButton

    private var mPauseDrawable: Drawable? = null
    private var mPlayDrawable: Drawable? = null

    private val mHandler = object : Handler(Looper.getMainLooper()) {
        override fun handleMessage(msg: Message) {
            super.handleMessage(msg)
            when (msg.what) {
                EVENT_SHOW_MENU -> {
                    mPlay.visibility = View.VISIBLE
                    mSeekBar.visibility = View.VISIBLE
                    mProgress.visibility = View.VISIBLE
                    mCollect.visibility = View.VISIBLE
                    mDownload.visibility = View.VISIBLE
                }
                EVENT_HIDE_MENU -> {
                    mPlay.visibility = View.GONE
                    mSeekBar.visibility = View.GONE
                    mProgress.visibility = View.GONE
                    mCollect.visibility = View.GONE
                    mDownload.visibility = View.GONE
                }
            }
        }
    }

    private val mSurfaceCallback = object : SurfaceHolder.Callback {
        override fun surfaceCreated(holder: SurfaceHolder) {
            Log.d(TAG, "surfaceCreated")
            mMediaPlayer.setDisplay(holder)
        }

        override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
            Log.d(TAG, "surfaceChanged")
        }

        override fun surfaceDestroyed(holder: SurfaceHolder) {
            Log.d(TAG, "surfaceDestroyed")
        }
    }

    override fun onAttach(context: Context) {
        super.onAttach(context)
        mContext = context
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let { mVideo = it.getParcelable(ARG_PARAM_VIDEO) }
        mVideoViewModel = ViewModelProvider(this).get(VideoViewModel::class.java)
        mPauseDrawable = ResourcesCompat.getDrawable(resources, R.drawable.pause, null)
        mPlayDrawable = ResourcesCompat.getDrawable(resources, R.drawable.play, null)
        mMediaPlayer = MediaPlayer()
        mMediaPlayer.setDataSource(mContext, Uri.parse(mVideo?.videoUrl))
        mMediaPlayer.setOnPreparedListener {
            mMediaPlayer.start()
            mVideoState = VideoState.PLAYING
            mMediaPlayer.isLooping = false
            mPlay.setImageDrawable(mPauseDrawable)
            setLoading(false)
            mProgress.text = getDateString(it.duration.toLong())
            mSeekBarJob = lifecycleScope.launch {
                while (true) {
                    Log.d(TAG, "onCreate: 更新进度条")
                    if (mVideoState == VideoState.PLAYING
                        && !mTouch
                        && mSeekBar.visibility == View.VISIBLE
                    ) {
                        val position = it.currentPosition
                        mSeekBar.progress = position
                    }
                    // 这是主线程，不delay会寄
                    delay(100)
                }
            }
            mSeekBar.max = it.duration
            mSeekBar.progress = 0
            reHideUI()
        }
        // FIXME: 增加对media player的监听, 然后显示加载动画
        mMediaPlayer.prepareAsync()
        mRotateAnimation = AnimationUtils.loadAnimation(mContext, R.anim.refresh_rotate)
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_video_playing, container, false)
        mPlay = view.findViewById(R.id.play)
        mSeekBar = view.findViewById(R.id.seek_bar)
        mProgress = view.findViewById(R.id.progress)
        mSurfaceView = view.findViewById(R.id.video_surface)
        mCollect = view.findViewById(R.id.collect)
        mDownload = view.findViewById(R.id.download)
        mLoading = view.findViewById(R.id.loading)
        mLoadingLayer = view.findViewById(R.id.layer_loading)

        setLoading(true)
        mSurfaceView.setOnClickListener { reHideUI() }
        mSeekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
            override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
                if (fromUser) {
                    mMediaPlayer.seekTo(progress.toLong(), MediaPlayer.SEEK_CLOSEST_SYNC)
                    Log.d(TAG, "onProgressChanged: progress = $progress")
                }
            }

            override fun onStartTrackingTouch(seekBar: SeekBar?) {
                mTouch = true
            }

            override fun onStopTrackingTouch(seekBar: SeekBar?) {
                mTouch = false
            }

        })
        mPlay.setOnClickListener {
            if (mVideoState == VideoState.PLAYING) {
                mMediaPlayer.pause()
                mPlay.setImageDrawable(mPlayDrawable)
                mVideoState = VideoState.PAUSE_BY_USER
            } else if ((mVideoState == VideoState.PAUSE_BY_USER)
                || (mVideoState == VideoState.PAUSE_BY_LIFECYCLE)
            ) {
                mMediaPlayer.start()
                mPlay.setImageDrawable(mPauseDrawable)
                mVideoState = VideoState.PLAYING
            }
            reHideUI()
        }

        mCollect.setOnClickListener {
            mVideo?.let { video ->
                video.seen = true
                video.collect = true
                mVideoViewModel.update(video)
            }
            reHideUI()
            Toast.makeText(mContext, "收藏成功!", Toast.LENGTH_SHORT).show()
        }

        mDownload.setOnClickListener {
            mVideo?.let { video ->
                AlertDialog.Builder(mContext)
                    .setTitle("下载")
                    .setMessage(mVideo?.title)
                    .setPositiveButton("下载") { _, _ ->
                        DownloadUtil.downloadVideo(mContext, video.videoUrl, true, video.title)
                    }
                    .create()
                    .show()
            }
        }

        mSurfaceHolder = mSurfaceView.holder
        mSurfaceHolder.addCallback(mSurfaceCallback)
        return view
    }

    override fun onResume() {
        super.onResume()
        Log.d(TAG, "onResume")
        if (mVideoState == VideoState.PAUSE_BY_LIFECYCLE) {
            mMediaPlayer.start()
            mVideoState = VideoState.PLAYING
            reHideUI()
        }
    }

    override fun onPause() {
        super.onPause()
        Log.d(TAG, "onPause")
    }

    override fun onStop() {
        super.onStop()
        Log.d(TAG, "onStop")
        if (mVideoState == VideoState.PLAYING) {
            mMediaPlayer.pause()
            mVideoState = VideoState.PAUSE_BY_LIFECYCLE
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.d(TAG, "onDestroy")
        mSeekBarJob?.cancel()
        mSurfaceHolder.removeCallback(mSurfaceCallback)
        mVideoState = VideoState.NONE
        mMediaPlayer.reset()
        mMediaPlayer.release()
    }

    private fun setLoading(enable: Boolean) {
        if (enable) {
            mLoadingLayer.visibility = View.VISIBLE
            mLoading.visibility = View.VISIBLE
            mLoading.startAnimation(mRotateAnimation)
        } else {
            mLoading.visibility = View.GONE
            mLoadingLayer.visibility = View.GONE
            mLoading.clearAnimation()
        }
    }

    private fun reHideUI() {
        mHandler.removeMessages(EVENT_HIDE_MENU)
        mHandler.sendEmptyMessage(EVENT_SHOW_MENU)
        mHandler.sendEmptyMessageDelayed(EVENT_HIDE_MENU, DELAY_HIDE)
    }

    /**
     * %tT-时分秒-15:44:21
     */
    private fun getDateString(milliseconds: Long): String {
        if (milliseconds < 0) return ""
        val date = Date(milliseconds)
        return String.format(Locale.getDefault(), "%tT", date)
    }

    companion object {
        const val ARG_PARAM_VIDEO = "video"
        private const val TAG = "VideoPlayingFragment"
        private const val EVENT_HIDE_MENU = 1
        private const val EVENT_SHOW_MENU = 2
        private const val DELAY_HIDE = 6000L
    }
}